home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 3006 / 3006.xpi / components / dhMP3Tunes.js < prev    next >
Text File  |  2010-01-15  |  18KB  |  464 lines

  1. /******************************************************************************
  2.  *            Copyright (c) 2006-2009 Michel Gutierrez. All Rights Reserved.
  3.  ******************************************************************************/
  4.  
  5. /**
  6.  * Constants.
  7.  */
  8.  
  9. const NS_DH_MP3TUNES_CID = Components.ID("{59dd53ca-8989-4e95-bc7a-996e8592886e}");
  10. const NS_DH_MP3TUNES_PROG_ID = "@downloadhelper.net/mp3tunes-manager;1";
  11. const DHNS = "http://downloadhelper.net/1.0#";
  12.  
  13. var Util=null;
  14. var IOS=null;
  15.  
  16. /**
  17. * Object constructor
  18. */
  19. function MP3Tunes() {
  20.     try {
  21.         this.token="5418414535";
  22.         //dump("[MP3Tunes] constructor\n");
  23.         var prefService=Components.classes["@mozilla.org/preferences-service;1"]
  24.                                            .getService(Components.interfaces.nsIPrefService);
  25.         this.pref=prefService.getBranch("dwhelper.mp3tunes.");
  26.     } catch(e) {
  27.         dump("!!! [MP3Tunes] constructor: "+e+"\n");
  28.     }
  29. }
  30.  
  31. MP3Tunes.prototype = {}
  32.  
  33. MP3Tunes.prototype.authenticateHandler = function(args,status,doc,httpStatus,text) {
  34.     //dump("[MP3Tunes] authenticateHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  35.     try {
  36.         var errorMessage="Invalid server response";
  37.         if(status && doc!=null) {
  38.             var authStatus=Util.xpGetString(doc.documentElement,"/mp3tunes/status");
  39.             if(authStatus=="1") {
  40.                 this.sessionId=Util.xpGetString(doc.documentElement,"/mp3tunes/session_id");
  41.                 args.observer.observe(this,"mp3tunes-auth-succeeded","");
  42.                 return;
  43.             } else {
  44.                 errorMessage=Util.xpGetString(doc.documentElement,"/mp3tunes/errorMessage");
  45.                 //dump("[MP3Tunes] authenticate failed: "+errorMessage+"\n");                
  46.             }
  47.         }
  48.         args.observer.observe(this,"mp3tunes-auth-failed",errorMessage);
  49.     } catch(e) {
  50.         dump("!!! [MP3Tunes] authenticate error: "+e+"\n");
  51.         args.observer.observe(this,"mp3tunes-auth","Internal error: "+e);
  52.     }
  53. }
  54.  
  55. MP3Tunes.prototype.authenticate = function(user,password,observer) {
  56.     try {
  57.     //dump("[MP3Tunes] authenticate("+user+","+password+",...)\n");
  58.     var url="https://shop.mp3tunes.com/api/v1/login?output=xml&username="+encodeURIComponent(user)+
  59.         "&password="+encodeURIComponent(password)+"&partner_token="+encodeURIComponent(this.token);
  60.     //dump("url="+url+"\n");
  61.     var uri = IOS.newURI(url, null, null);
  62.     var channel = IOS.newChannelFromURI(uri);
  63.     var listener = new XMLStreamListener(this,"authenticateHandler",{observer: observer});
  64.     channel.notificationCallbacks = listener;
  65.     channel.asyncOpen(listener, null);
  66.  
  67.     } catch(e) { dump("!!! [MP3Tunes] authenticate error: "+e+"\n"); };
  68. }
  69.  
  70. MP3Tunes.prototype.accountStatusHandler2 = function(args,status,doc,httpStatus,text) {
  71.     //dump("[MP3Tunes] accountStatusHandler2("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  72.     try {
  73.         var errorMessage="Invalid server response";
  74.         if(status && doc!=null) {
  75.             var lockerType=Util.xpGetString(doc.documentElement,"/mp3tunes/user/lockerType");
  76.             var expired=Util.xpGetString(doc.documentElement,"/mp3tunes/user/expired");
  77.             var accountStatus="free";
  78.             if(/premium/i.test(lockerType) && expired=="0")
  79.                 accountStatus="premium";
  80.             this.pref.setCharPref("last-status",accountStatus);
  81.             args.observer.observe(this,"mp3tunes-account-status",accountStatus);
  82.             return;
  83.         }
  84.         this.pref.setCharPref("last-status",errorMessage);
  85.         args.observer.observe(this,"mp3tunes-account-status",errorMessage);
  86.     } catch(e) {
  87.         dump("!!! [MP3Tunes] accountStatus2 error: "+e+"\n");
  88.         var errorMessage="Internal error: "+e;
  89.         this.pref.setCharPref("last-status",errorMessage);
  90.         args.observer.observe(this,"mp3tunes-account-status",errorMessage);
  91.     }
  92. }
  93.  
  94. MP3Tunes.prototype.accountStatusHandler = function(args,status,doc,httpStatus,text) {
  95.     //dump("[MP3Tunes] accountStatusHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  96.     try {
  97.         var errorMessage="Invalid server response";
  98.         if(status && doc!=null) {
  99.             var authStatus=Util.xpGetString(doc.documentElement,"/mp3tunes/status");
  100.             if(authStatus=="1") {
  101.                 this.sessionId=Util.xpGetString(doc.documentElement,"/mp3tunes/session_id");
  102.                 var url="https://shop.mp3tunes.com/api/v1/accountData?output=xml&sid=" + this.sessionId;
  103.                 //dump("url="+url+"\n");
  104.                 var uri = IOS.newURI(url, null, null);
  105.                 var channel = IOS.newChannelFromURI(uri);
  106.                 var listener = new XMLStreamListener(this,"accountStatusHandler2",{observer: args.observer});
  107.                 channel.notificationCallbacks = listener;
  108.                 channel.asyncOpen(listener, null);
  109.                 return;
  110.             } else {
  111.                 errorMessage=Util.xpGetString(doc.documentElement,"/mp3tunes/errorMessage");
  112.                 //dump("[MP3Tunes] authenticate failed: "+errorMessage+"\n");                
  113.             }
  114.         }
  115.         this.pref.setCharPref("last-status",errorMessage);
  116.         args.observer.observe(this,"mp3tunes-account-status",errorMessage);
  117.     } catch(e) {
  118.         dump("!!! [MP3Tunes] accountStatus error: "+e+"\n");
  119.         var errorMessage="Internal error: "+e;
  120.         this.pref.setCharPref("last-status",errorMessage);
  121.         args.observer.observe(this,"mp3tunes-account-status",errorMessage);
  122.     }
  123. }
  124.  
  125. MP3Tunes.prototype.accountStatus = function(user,password,observer) {
  126.     try {
  127.     //dump("[MP3Tunes] accountStatus("+user+","+password+",...)\n");
  128.     var url="https://shop.mp3tunes.com/api/v1/login?output=xml&username="+encodeURIComponent(user)+
  129.         "&password="+encodeURIComponent(password)+"&partner_token="+encodeURIComponent(this.token);
  130.     //dump("url="+url+"\n");
  131.     var uri = IOS.newURI(url, null, null);
  132.     var channel = IOS.newChannelFromURI(uri);
  133.     var listener = new XMLStreamListener(this,"accountStatusHandler",{observer: observer});
  134.     channel.notificationCallbacks = listener;
  135.     channel.asyncOpen(listener, null);
  136.  
  137.     } catch(e) { dump("!!! [MP3Tunes] accountStatus error: "+e+"\n"); };
  138. }
  139.  
  140. MP3Tunes.prototype.createAccountHandler = function(args,status,doc,httpStatus,text) {
  141.     //dump("[MP3Tunes] createAccountHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  142.     try {
  143.         var errorMessage="Invalid server response";
  144.         if(status && doc!=null) {
  145.             var accountStatus=Util.xpGetString(doc.documentElement,"/mp3tunes/status");
  146.             if(accountStatus=="1") {
  147.                 this.sessionId=Util.xpGetString(doc.documentElement,"/mp3tunes/session_id");
  148.                 args.observer.observe(this,"mp3tunes-create-account-succeeded","");
  149.                 return;
  150.             } else {
  151.                 errorMessage=Util.xpGetString(doc.documentElement,"/mp3tunes/errorMessage");
  152.                 //dump("[MP3Tunes] createAccount failed: "+errorMessage+"\n");                
  153.             }
  154.         }
  155.         args.observer.observe(this,"mp3tunes-create-account-failed",errorMessage);
  156.     } catch(e) {
  157.         dump("!!! [MP3Tunes] createAccount error: "+e+"\n");
  158.         args.observer.observe(this,"mp3tunes-create-account-failed","Internal error: "+e);
  159.     }
  160. }
  161.  
  162. MP3Tunes.prototype.createAccount = function(user,password,firstname,lastname,observer) {
  163.     try {
  164.     //dump("[MP3Tunes] createAccount("+user+","+password+","+firstname+","+lastname+",...)\n");
  165.     var url="https://shop.mp3tunes.com/api/v1/createAccount?output=xml&email="+encodeURIComponent(user)+
  166.         "&password="+encodeURIComponent(password)+
  167.         "&firstname="+encodeURIComponent(firstname)+
  168.         "&lastname="+encodeURIComponent(lastname)+
  169.         "&partner_token="+encodeURIComponent(this.token);
  170.     //dump("url="+url+"\n");
  171.     var uri = IOS.newURI(url, null, null);
  172.     var channel = IOS.newChannelFromURI(uri);
  173.     var listener = new XMLStreamListener(this,"createAccountHandler",{observer: observer});
  174.     channel.notificationCallbacks = listener;
  175.     channel.asyncOpen(listener, null);
  176.  
  177.     } catch(e) { dump("!!! [MP3Tunes] createAccount error: "+e+"\n"); };
  178. }
  179.  
  180. MP3Tunes.prototype.uploadFileHandler = function(args,status,doc,httpStatus,text) {
  181.     //dump("[MP3Tunes] uploadFileHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  182.     try {
  183.         args.inputStream.close();
  184.         if(status) {
  185.             args.observer.observe(this,"mp3tunes-upload-file-succeeded","");
  186.             return;
  187.         }
  188.         args.observer.observe(this,"mp3tunes-upload-file-failed","HTTP code "+httpStatus);
  189.     } catch(e) {
  190.         dump("!!! [MP3Tunes] uploadFile error: "+e+"\n");
  191.         args.observer.observe(this,"mp3tunes-upload-file-failed","Internal error: "+e);
  192.     }
  193. }
  194.  
  195. MP3Tunes.prototype.uploadFile = function(file,properties,observer) {
  196.     try {
  197.         //dump("[MP3Tunes] uploadFile("+file.path+",...)\n");
  198.         //dump("[MP3Tunes] uploadFile(): file exist="+file.exists()+"\n");
  199.         //dump("[MP3Tunes] uploadFile(): file size="+file.fileSize+"\n");
  200.  
  201.         var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
  202.         createInstance(Components.interfaces.nsIFileInputStream);
  203.         fis.init(file,1,0,false);
  204.         var signer = Components.classes["@mozilla.org/security/hash;1"]
  205.                                     .createInstance(Components.interfaces.nsICryptoHash);
  206.         signer.init(signer.MD5);
  207.         const PR_UINT32_MAX = 0xffffffff;
  208.         signer.updateFromStream(fis,PR_UINT32_MAX);
  209.         var hash = signer.finish(false);
  210.         function toHexString(charCode)
  211.         {
  212.           return ("0" + charCode.toString(16)).slice(-2);
  213.         }
  214.         var t=[];
  215.         for(var i in hash) {
  216.             t.push(toHexString(hash.charCodeAt(i)));
  217.         }
  218.         var md5=t.join("");
  219.         //dump("[MP3Tunes] uploadFile: md5="+md5+"\n");
  220.         
  221.         if(properties) {
  222.             Util.setPropsString(properties,"cv-md5",md5);
  223.         }
  224.         
  225.         var url="http://content.mp3tunes.com/storage/lockerPut/"+md5+
  226.             "?sid="+encodeURIComponent(this.sessionId)+
  227.             "&partner_token="+encodeURIComponent(this.token);
  228.         //dump("url="+url+"\n");
  229.         var uri = IOS.newURI(url, null, null);
  230.         var channel = IOS.newChannelFromURI(uri);
  231.         var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);
  232.         httpChannel.setRequestHeader("X-Original-Filename",file.leafName,false);
  233.         if(properties) {
  234.             var artistName=Util.getPropsString(properties,"mp3tunes-artist-name");
  235.             if(artistName.length)
  236.                 httpChannel.setRequestHeader("X-MP3tunes-Artist-Name",artistName,false);
  237.             var albumTitle=Util.getPropsString(properties,"mp3tunes-album-title");
  238.             if(albumTitle.length)
  239.                 httpChannel.setRequestHeader("X-MP3tunes-Album-Title",albumTitle,false);
  240.             var trackTitle=Util.getPropsString(properties,"mp3tunes-track-title");
  241.             if(trackTitle.length)
  242.                 httpChannel.setRequestHeader("X-MP3tunes-Track-Title",trackTitle,false);
  243.             var trackNumber=Util.getPropsString(properties,"mp3tunes-track-number");
  244.             if(trackNumber.length)
  245.                 httpChannel.setRequestHeader("X-MP3tunes-Track-Number",trackNumber,false);
  246.             var year=Util.getPropsString(properties,"mp3tunes-year");
  247.             if(year.length)
  248.                 httpChannel.setRequestHeader("X-MP3tunes-Year",year,false);
  249.         }
  250.         httpChannel.requestMethod = "PUT";
  251.         fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
  252.             createInstance(Components.interfaces.nsIFileInputStream);
  253.         fis.init(file,1,0,false);
  254.         var uploadChannel = channel.QueryInterface(Components.interfaces.nsIUploadChannel);
  255.         uploadChannel.setUploadStream(fis, "application/x-binary", -1);
  256.  
  257.         var listener = new XMLStreamListener(this,"uploadFileHandler",{observer: observer, inputStream: fis});
  258.         channel.notificationCallbacks = listener;
  259.         channel.asyncOpen(listener, null);
  260.  
  261.     } catch(e) { dump("!!! [MP3Tunes] uploadFile error: "+e+"\n"); };
  262. }
  263.  
  264.  
  265. MP3Tunes.prototype.sendToPhoneHandler = function(args,status,doc,httpStatus,text) {
  266.     //dump("[MP3Tunes] setToPhoneHandler("+args+","+status+","+doc+","+httpStatus+",<text>)\n<text>="+text+"\n");
  267.     try {
  268.         var errorMessage="Invalid server response";
  269.         if(status && doc!=null) {
  270.             var accountStatus=Util.xpGetString(doc.documentElement,"/mp3tunes/status");
  271.             if(accountStatus=="1") {
  272.                 this.sessionId=Util.xpGetString(doc.documentElement,"/mp3tunes/session_id");
  273.                 args.observer.observe(this,"mp3tunes-send-to-phone-succeeded","");
  274.                 return;
  275.             } else {
  276.                 errorMessage=Util.xpGetString(doc.documentElement,"/mp3tunes/errorMessage");
  277.                 //dump("[MP3Tunes] sendToPhone failed: "+errorMessage+"\n");                
  278.             }
  279.         }
  280.         args.observer.observe(this,"mp3tunes-send-to-phone-failed",errorMessage);
  281.     } catch(e) {
  282.         dump("!!! [MP3Tunes] sendToPhone error: "+e+"\n");
  283.         args.observer.observe(this,"mp3tunes-send-to-phone-failed","Internal error: "+e);
  284.     }
  285. }
  286.  
  287. MP3Tunes.prototype.sendToPhone = function(key, phonenumber, observer) {
  288.     try {
  289.     //dump("[MP3Tunes] sendToPhone("+key+","+phonenumber+",...)\n");
  290.     var url="https://shop.mp3tunes.com/api/v1/sendSMS?output=xml&sid="+this.sessionId+
  291.         "&key="+encodeURIComponent(key)+
  292.         "&number="+encodeURIComponent(phonenumber.replace(/[^0-9]/g,''))+
  293.         "&prefix=1";
  294.     //dump("url="+url+"\n");
  295.     var uri = IOS.newURI(url, null, null);
  296.     var channel = IOS.newChannelFromURI(uri);
  297.     var listener = new XMLStreamListener(this,"sendToPhoneHandler",{observer: observer});
  298.     channel.notificationCallbacks = listener;
  299.     channel.asyncOpen(listener, null);
  300.  
  301.     } catch(e) { dump("!!! [MP3Tunes] sendToPhone error: "+e+"\n"); };
  302. }
  303.  
  304.  
  305.  
  306. MP3Tunes.prototype.QueryInterface = function(iid) {
  307.     //dump("[MP3Tunes] QueryInterface("+iid+")\n");
  308.     if(    iid.equals(Components.interfaces.dhIMP3Tunes) ||
  309.         iid.equals(Components.interfaces.nsISupports)) {
  310.             return this;
  311.         }
  312.     throw Components.results.NS_ERROR_NO_INTERFACE;
  313. }
  314.  
  315.  
  316. var vMP3TunesModule = {
  317.     firstTime: true,
  318.     
  319.     /*
  320.      * RegisterSelf is called at registration time (component installation
  321.      * or the only-until-release startup autoregistration) and is responsible
  322.      * for notifying the component manager of all components implemented in
  323.      * this module.  The fileSpec, location and type parameters are mostly
  324.      * opaque, and should be passed on to the registerComponent call
  325.      * unmolested.
  326.      */
  327.     registerSelf: function (compMgr, fileSpec, location, type) {
  328.  
  329.         if (this.firstTime) {
  330.             this.firstTime = false;
  331.             throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
  332.         }
  333.         //dump("*** Registering MP3Tunes\n");
  334.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  335.         compMgr.registerFactoryLocation(NS_DH_MP3TUNES_CID,
  336.                                         "MP3Tunes",
  337.                                         NS_DH_MP3TUNES_PROG_ID, 
  338.                                         fileSpec,
  339.                                         location,
  340.                                         type);
  341.         //dump("*** Registered MP3Tunes\n");
  342.     },
  343.  
  344.     unregisterSelf: function(compMgr, fileSpec, location) {
  345.         compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  346.         compMgr.unregisterFactoryLocation(NS_DH_MP3TUNES_CID, fileSpec);
  347.     },
  348.  
  349.     /*
  350.      * The GetClassObject method is responsible for producing Factory and
  351.      * SingletonFactory objects (the latter are specialized for services).
  352.      */
  353.     getClassObject: function (compMgr, cid, iid) {
  354.         if (!cid.equals(NS_DH_MP3TUNES_CID)) {
  355.             throw Components.results.NS_ERROR_NO_INTERFACE;
  356.         }
  357.  
  358.         if (!iid.equals(Components.interfaces.nsIFactory)) {
  359.             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  360.         }
  361.  
  362.         return this.vMP3TunesFactory;
  363.     },
  364.  
  365.     /* factory object */
  366.     vMP3TunesFactory: {
  367.         /*
  368.          * Construct an instance of the interface specified by iid, possibly
  369.          * aggregating it with the provided outer.  (If you don't know what
  370.          * aggregation is all about, you don't need to.  It reduces even the
  371.          * mightiest of XPCOM warriors to snivelling cowards.)
  372.          */
  373.         createInstance: function (outer, iid) {
  374.             if (outer != null) {
  375.                 throw Components.results.NS_ERROR_NO_AGGREGATION;
  376.             }
  377.     
  378.             //dump("MP3Tunes: create instance\n");
  379.  
  380.             if(Util==null) 
  381.                 Util=Components.classes["@downloadhelper.net/util-service;1"]
  382.                     .getService(Components.interfaces.dhIUtilService);
  383.             if(IOS==null)
  384.                 IOS= Components.classes["@mozilla.org/network/io-service;1"]
  385.                     .getService(Components.interfaces.nsIIOService);
  386.  
  387.             return new MP3Tunes().QueryInterface(iid);
  388.         }
  389.     },
  390.  
  391.     /*
  392.      * The canUnload method signals that the component is about to be unloaded.
  393.      * C++ components can return false to indicate that they don't wish to be
  394.      * unloaded, but the return value from JS components' canUnload is ignored:
  395.      * mark-and-sweep will keep everything around until it's no longer in use,
  396.      * making unconditional ``unload'' safe.
  397.      *
  398.      * You still need to provide a (likely useless) canUnload method, though:
  399.      * it's part of the nsIModule interface contract, and the JS loader _will_
  400.      * call it.
  401.      */
  402.     canUnload: function(compMgr) {
  403.         return true;
  404.     }
  405. };
  406.  
  407. function NSGetModule(compMgr, fileSpec) {
  408.     return vMP3TunesModule;
  409. }
  410.  
  411. function XMLStreamListener(service,callback,args) {
  412.     this.service=service;
  413.     this.callback=callback;
  414.     this.args=args;
  415. }
  416.  
  417. XMLStreamListener.prototype={
  418.     QueryInterface: function(iid) {
  419.         if (iid.equals(Components.interfaces.nsISupports) || 
  420.             iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
  421.             iid.equals(Components.interfaces.nsIStreamListener)) {
  422.             return this;
  423.         }
  424.         throw Components.results.NS_ERROR_NO_INTERFACE;
  425.     },
  426.     onStartRequest: function(request,context) {
  427.         this.data="";
  428.     },
  429.     onDataAvailable: function(request,context,inputStream,offset,count) {
  430.         var sstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
  431.                .createInstance(Components.interfaces.nsIConverterInputStream);
  432.         sstream.init(inputStream, "utf-8", 256, 
  433.             Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
  434.  
  435.         var str={};
  436.         var n=sstream.readString(128,str);
  437.         while(n>0) {
  438.             this.data+=str.value;
  439.             str={};
  440.             n=sstream.readString(128,str);
  441.         }
  442.     },
  443.     onStopRequest: function(request,context,nsresult) {
  444.         var responseStatus=request.QueryInterface(Components.interfaces.nsIHttpChannel).responseStatus;
  445.         if(responseStatus==200) {
  446.             var parser=Components.classes["@mozilla.org/xmlextras/domparser;1"].
  447.                 createInstance(Components.interfaces.nsIDOMParser);
  448.             var doc=parser.parseFromString(this.data,"text/xml");
  449.             this.service[this.callback](this.args,true,doc,responseStatus,this.data);
  450.         } else {
  451.             this.service[this.callback](this.args,false,null,responseStatus,this.data);
  452.         }
  453.     },
  454.     getInterface: function(iid) {
  455.         if (iid.equals(Components.interfaces.nsISupports) || 
  456.             iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
  457.             iid.equals(Components.interfaces.nsIStreamListener)) {
  458.             return this;
  459.         }
  460.         return null;
  461.     },
  462. }
  463.  
  464.